#ifndef DHD_CCONNECTION_H
#define DHD_CCONNECTION_H

#include <stdint.h>

#include <map>
#include <queue>

#include "srp.h"

#include "socket_io.h"
#include "event_notifier.h"
#include "c_config.h"
#include "c_interaction.h"

namespace dhd
{   
namespace client
{
   using boost::asio::ip::tcp;
   
 
   typedef std::map< uint16_t, PInteraction >  ReplyMap;

   
   struct IConnectionHandler
   {
       virtual void connection_on_connect() = 0;
       virtual void connection_on_disconnect() = 0;
       virtual void connection_on_reply( PInteraction ) = 0;
       virtual void connection_on_unsolicited( const ToClient & ) = 0;
   };
   
   
   
   class Connection
   {
       boost::mutex                 conn_mutex;
       ServerCFG                   *conf;
       boost::asio::io_service     *io_service;
       tcp::endpoint                svr_endpoint;
       
       boost::asio::ssl::context   *ssl_ctx;
       
       tcp::socket                 *sock;
       ssl_socket                  *ssl_sock;
       PSocketIO                    sock_io;
      
       SRPUser                     *srp_usr;
       
       ReplyMap                     pending_replies;
       
       IConnectionHandler          *handler;
       
       boost::asio::deadline_timer  reconnect_timer;
       bool                         connected;
       bool                         got_server_root;
       bool                         authenticated;
       bool                         srp_sent_m;
       
       
       void on_read_error( const char * msg, bool reconnect = true );
       
       void on_disconnect( bool reconnect = true );
              
       void async_connect();
       
       void async_reconnect( const boost::system::error_code& error );
       
       void do_ssl_handshake( const boost::system::error_code& error );
       
       void on_async_connect_complete( const boost::system::error_code& error );
       
       void authentication_complete();
       
       void handle_message( uint16_t request_id, PBuffer header, PBuffer buffer );
       
       void handle_authentication_message( const ToClient & result );
       
     public:
       
       Connection( ServerCFG * cfg, IConnectionHandler *_handler, boost::asio::io_service *_io_svc );
       
       ~Connection();
       
       void send_interaction( PInteraction i );
       
       bool is_connected() { return connected; }
   };
   
} // end namespace dhd::client
} // end namespace dhd

#endif
